package com.dynaBlaster;

import java.util.ArrayList;
import java.util.Random;

import com.dynaBlaster.gameElements.Bomb;
import com.dynaBlaster.gameElements.Creature;
import com.dynaBlaster.gameElements.Hero;
import com.dynaBlaster.gameElements.MonsterGlut;
import com.dynaBlaster.gameElements.PumpkinGhost;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.TextView;

public class DynaView extends BoardView implements SensorEventListener, OnTouchListener {

	public static final String LOG_TAG = "DynaView";
	/**
	 * Current mode of application: READY to run, RUNNING, or you have already
	 * lost. static final ints are used instead of an enum for performance
	 * reasons.
	 */
	private int mMode = READY;
	public static final int PAUSE = 0;
	public static final int READY = 1;
	public static final int RUNNING = 2;
	public static final int GAME_LOST = 3;
	public static final int GAME_WON = 4;

	public int control_mode;
	public static final int CONTROL_TOUCH_AND_KEYBORD = 0;
	public static final int CONTROL_SENSOR_AND_KEYBORD = 1;

	public enum Area {
		FREE(1), WALL(2), CONCRETE(3), EXIT(4);
		public int nr;

		Area(int i) {
			nr = i;
		}
	}

	/**
	 * mLastMove: tracks the absolute time when the snake last moved, and is
	 * used to determine if a move should be made based on mMoveDelay.
	 */
	private long mLastMove;

	/**
	 * mStatusText: text shows to the user in some run states
	 */
	private TextView mStatusText;

	/**
	 * 
	 * hero coordinates
	 */
	public static final int HERO_START_X = 1, HERO_START_Y = 1;

	private static final int exitX = HERO_START_X + 2, exitY = HERO_START_Y + 2;
	private Hero mHero;

	private ArrayList<Creature> monsters;

	private ArrayList<Bomb> bombs;

	private Resources r = this.getContext().getResources();

	boolean upKeyPressed, downKeyPressed, leftKeyPressed, rightKeyPressed;

	boolean isHeroMoving = false;
	long tapStart;
	
	private Bitmap bombPlanting;

	/**
     */
	public static final Random RNG = new Random();
	
	public static  boolean  BOARD_CLEAR=false;

	/**
	 * Create a simple handler that we can use to cause animation to happen. We
	 * set ourselves as a target and we can use the sleep() function to cause an
	 * update/invalidate to occur at a later date.
	 */
	private RefreshHandler mRedrawHandler = new RefreshHandler();

	class RefreshHandler extends Handler {

		@Override
		public void handleMessage(Message msg) {
			DynaView.this.update();
			DynaView.this.invalidate();
		}

		public void sleep(long delayMillis) {
			this.removeMessages(0);
			sendMessageDelayed(obtainMessage(0), delayMillis);
		}
	};

	/**
	 * Constructs a SnakeView based on inflation from XML
	 * 
	 * @param context
	 * @param attrs
	 */
	public DynaView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public DynaView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	private void init() {
		setFocusable(true);
		mTileArray = new Bitmap[5];
		loadTile(Area.FREE.nr, r.getDrawable(R.drawable.free));
		loadTile(Area.WALL.nr, r.getDrawable(R.drawable.wall));
		loadTile(Area.CONCRETE.nr, r.getDrawable(R.drawable.concrete));
		loadTile(Area.EXIT.nr, r.getDrawable(R.drawable.exit));
		
		Drawable bomb=r.getDrawable(R.drawable.bomb);
		bombPlanting = Bitmap.createBitmap(GameConfg.PLANT_BOMB_SIZE,GameConfg.PLANT_BOMB_SIZE, Bitmap.Config.ARGB_8888);
		Canvas canvas = new Canvas(bombPlanting);
		bomb.setBounds(0, 0, GameConfg.PLANT_BOMB_SIZE, GameConfg.PLANT_BOMB_SIZE);
		bomb.draw(canvas);
	}

	private void initNewGame() {

		mHero = new Hero(this);
		mHero.setPos(getAbsCoord(new Point(HERO_START_X, HERO_START_Y)));

		monsters = new ArrayList<Creature>();
		bombs = new ArrayList<Bomb>();

		initWalls();
		initBoard();

		for (int i = 0; i < GameConfg.COUNT_1ST_LEVEL_CREATURES; i++) {
			if (!addEnemyToGame(new PumpkinGhost(this)))
				break;
		}

		for (int i = 0; i < GameConfg.COUNT_2ND_LEVEL_CREATURES; i++) {
			if (!addEnemyToGame(new MonsterGlut(this)))
				break;
		}

		if (control_mode == CONTROL_SENSOR_AND_KEYBORD)
			initSensor();

	}

	/**
	 * 
	 * @param c
	 * @return if creature was added
	 */
	boolean addEnemyToGame(Creature c) {
		int safety_counter = 0;
		Point field;
		do {
			field = getRandomFreeField();
			safety_counter++;
			if (safety_counter > GameConfg.RANDOM_SAFETY_COUNTER)
				break;
		} while (field != null && (isCreatureOnField(field) || isInHeroStartPoints(field)));

		if (safety_counter > GameConfg.RANDOM_SAFETY_COUNTER || field == null) {
			Log.w(LOG_TAG, "addEnemyToGame: brak miejsca,losowanie przerwane ");
			return false;
		}
		c.setPos(getAbsCoord(field));
		monsters.add(c);
		return true;
	}

	boolean isCreatureOnField(Point field) {
		for (Creature c : monsters) {
			if (getBoardCoord(c.getPos()).equals(field))
				return true;
		}
		return false;
	}

	private Point getRandomFreeField() {
		int safety_counter = 0;
		int x, y;
		do {
			x = RNG.nextInt(mXTileCount - 1) + 1;
			y = RNG.nextInt(mYTileCount - 1) + 1;
			safety_counter++;
			if (safety_counter > GameConfg.RANDOM_SAFETY_COUNTER)
				break;
		} while (mTileGrid[x][y] != Area.FREE.nr);

		if (safety_counter > GameConfg.RANDOM_SAFETY_COUNTER) {
			Log.w(LOG_TAG, "getRandomFreeField: brak miejsca,losowanie przerwane ");
			return null;
		}
		return new Point(x, y);
	}

	public boolean isFree(Point toCheck, boolean allowCreatures, boolean allowWalls, Bomb bombToIgnore) {

		// chceck board content
		Point field = BoardView.getBoardCoord(toCheck);
		if (!allowWalls) {
			if (mTileGrid[field.x][field.y] != Area.FREE.nr && mTileGrid[field.x][field.y] != Area.EXIT.nr)
				return false;
		} else if (mTileGrid[field.x][field.y] == Area.CONCRETE.nr)
			return false;
		//    	
		// check bombs
		for (Bomb b : bombs)
			if (b.isOverPoint(toCheck))
				if (b != bombToIgnore)
					return false;

		//		
		// // check creatures
		//			
		if (allowCreatures)
			return true;
		else {
			for (Creature c : monsters) {
				if (c.isOverPoint(toCheck)) {
					return false;
				}
			}
			return true;
		}

	}

	@Override
	public void onDraw(Canvas canvas) {
		super.onDraw(canvas);

		if (mMode == RUNNING || mMode == GAME_LOST || mMode == GAME_WON) {
			for (Bomb b : bombs) {
				b.draw(canvas);
			}

			mHero.draw(canvas);

			for (Creature c : monsters) {
				c.draw(canvas);
			}
			
			canvas.drawBitmap(bombPlanting, 0,mYTileCount*mTileSize - GameConfg.PLANT_BOMB_SIZE , new Paint());

		} else if (mMode == READY) {
			Paint paint = new Paint();
			paint.setColor(Color.GRAY);
			paint.setStrokeWidth(9);
			canvas.drawLine(0, 250, 350, 250, paint);
		}
	}

	public void initWalls() {
		for (int x = 0; x < mXTileCount; x++) {
			setTile(Area.CONCRETE.nr, x, 0);
			setTile(Area.CONCRETE.nr, x, mYTileCount - 1);
		}
		for (int y = 1; y < mYTileCount - 1; y++) {
			setTile(Area.CONCRETE.nr, 0, y);
			setTile(Area.CONCRETE.nr, mXTileCount - 1, y);
		}
	}
	public int[] probability = new int[] { Area.WALL.nr, Area.WALL.nr, Area.WALL.nr, Area.FREE.nr, Area.FREE.nr,
			Area.FREE.nr, Area.FREE.nr, Area.FREE.nr };
	public void initBoard() {
		

		for (int x = 1; x < mXTileCount - 1; x++)
			for (int y = 1; y < mYTileCount - 1; y++) {
				if (x % 2 == 0 && y % 2 == 0) {
					setTile(Area.CONCRETE.nr, x, y);
				} else {
					int ind = RNG.nextInt(probability.length);
					if (DynaView.BOARD_CLEAR)
						setTile(Area.FREE.nr, x, y);
					else 
						setTile(probability[ind], x, y);
				}
			}

		// tam gdzie hero zaczyna musi byc puste
		setTile(Area.FREE.nr, HERO_START_X, HERO_START_Y);
		setTile(Area.FREE.nr, HERO_START_X + 1, HERO_START_Y);
		setTile(Area.FREE.nr, HERO_START_X, HERO_START_Y + 1);

		// exit
		if (!DynaView.BOARD_CLEAR){
			setTile(Area.EXIT.nr, exitX, exitY);
		}
			
		

	}

	boolean isInHeroStartPoints(Point field) {
		if (field.equals(new Point(HERO_START_X, HERO_START_Y))
				|| field.equals(new Point(HERO_START_X + 1, HERO_START_Y))
				|| field.equals(new Point(HERO_START_X, HERO_START_Y + 1)))
			return true;
		return false;
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent msg) {

		if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
			if (mMode == READY || mMode == GAME_LOST || mMode == GAME_WON) {

				initNewGame();
				setMode(RUNNING);
				update();
				return (true);
			}

			if (mMode == PAUSE) {
				/*
				 * If the game is merely paused, we should just continue where
				 * we left off.
				 */
				setMode(RUNNING);
				update();
				return (true);
			}

			mHero.setDir(Creature.Direction.NORTH);
			// mHero.move();
			upKeyPressed = true;
			return (true);
		}

		if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
			mHero.setDir(Creature.Direction.SOUTH);
			// mHero.move();
			downKeyPressed = true;
			return (true);
		}

		if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
			mHero.setDir(Creature.Direction.WEST);
			// mHero.move();
			leftKeyPressed = true;
			return (true);
		}

		if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
			mHero.setDir(Creature.Direction.EAST);
			// mHero.move();
			rightKeyPressed = true;
			return (true);
		}
		if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_SPACE) {

			plantBomb();

			return (true);
		}

		return super.onKeyDown(keyCode, msg);
	}

	private void plantBomb() {
		if (!mHero.canPlantBomb())
			return;

		Point bombBoardCoord = getBoardCoord(mHero.getPos());
		boolean isThereBomb = false;
		for (Bomb b : bombs)
			if (getBoardCoord(b.getPos()).equals(bombBoardCoord)) {
				isThereBomb = true;
				break;
			}
		if (!isThereBomb) {
			Bomb bomb = new Bomb(this, System.currentTimeMillis(), mHero);
			bomb.setPos(getAbsCoord(bombBoardCoord));
			this.bombs.add(bomb);
			mHero.setJustPlantedBomb(bomb);
		}

	}

	@Override
	public boolean onKeyUp(int keyCode, KeyEvent msg) {
		if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
			upKeyPressed = false;
			return (true);
		}

		if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
			downKeyPressed = false;
			return (true);
		}

		if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
			leftKeyPressed = false;
			return (true);
		}

		if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
			rightKeyPressed = false;
			return (true);
		}

		return super.onKeyUp(keyCode, msg);
	}

	/**
	 * Sets the TextView that will be used to give information (such as "Game
	 * Over" to the user.
	 * 
	 * @param newView
	 */
	public void setTextView(TextView newView) {
		mStatusText = newView;
	}

	/**
	 * Updates the current mode of the application (RUNNING or PAUSED or the
	 * like) as well as sets the visibility of textview for notification
	 * 
	 * @param newMode
	 */
	public void setMode(int newMode) {
		int oldMode = mMode;
		mMode = newMode;

		if (newMode == RUNNING & oldMode != RUNNING) {
			mStatusText.setVisibility(View.INVISIBLE);
			update();
			return;
		}

		CharSequence str = "";
		if (newMode == PAUSE) {
			str = r.getText(R.string.mode_pause);
		}
		if (newMode == READY) {
			str = r.getText(R.string.mode_ready);
		}
		if (newMode == GAME_LOST) {
			str = r.getString(R.string.mode_lose);
		}
		if (newMode == GAME_WON) {
			str = r.getString(R.string.mode_won);
		}

		mStatusText.setText(str);
		mStatusText.setVisibility(View.VISIBLE);
	}
	
	public int getMode(){
		return mMode;
	}

	/**
	 * Handles the basic update loop, checking to see if we are in the running
	 * state, determining if a move should be made, updating the snake's
	 * location.
	 */
	public void update() {
		if (mMode == RUNNING) {
			long now = System.currentTimeMillis();

			if (now - mLastMove > GameConfg.GAME_SPEED) {
				updateGame();
				mLastMove = now;
			}
			mRedrawHandler.sleep(GameConfg.GAME_SPEED);
		}

	}

	private void updateGame() {

		ArrayList<Bomb> alive = new ArrayList<Bomb>();
		for (Bomb b : bombs) {
			b.updateState(System.currentTimeMillis());
			if (!b.isDead())
				alive.add(b);
		}

		this.bombs = alive;

		for (Creature c : monsters)
			c.move();

		// creatures kill
		// for(Creature c : monsters)
		// if (c.touchesCreature(mHero)){
		// setMode(GAME_LOST);
		// return;
		// }

		// bombs kill hero
		for (Bomb b : bombs)
			if (b.touchesCreature(mHero)) {
				setMode(GAME_LOST);
				return;
			}
		// bombs kill creatures

		for (Bomb b : bombs)
			for (Creature c : monsters)
				if (b.touchesCreature(c)) {
					c.kill();
				}

		ArrayList<Creature> aliveCreats = new ArrayList<Creature>();
		for (Creature c : monsters)
			if (c.isAlive())
				aliveCreats.add(c);

		this.monsters = aliveCreats;

		// button control
		if (upKeyPressed || downKeyPressed || leftKeyPressed || rightKeyPressed)
			mHero.move();
		// touch control
		if (isHeroMoving)
			mHero.move();

		// winning
		if (mHero.isOverPoint(BoardView.getAbsCoord(new Point(exitX, exitY)))) {
			setMode(GAME_WON);
		}

	}

	public Resources getR() {
		return r;
	}

	/**
	 * Save game state so that the user does not lose anything if the game
	 * process is killed while we are in the background.
	 * 
	 * @return a Bundle with this view's state
	 */
	public Bundle saveState() {
		Bundle map = new Bundle();

		// map.putIntArray("mAppleList", coordArrayListToArray(mAppleList));
		// map.putInt("mDirection", Integer.valueOf(mDirection));
		// map.putInt("mNextDirection", Integer.valueOf(mNextDirection));
		// map.putLong("mMoveDelay", Long.valueOf(mMoveDelay));
		// map.putLong("mScore", Long.valueOf(mScore));
		// map.putIntArray("mSnakeTrail", coordArrayListToArray(mSnakeTrail));

		return map;
	}

	/**
	 * Restore game state if our process is being relaunched
	 * 
	 * @param icicle
	 *            a Bundle containing the game state
	 */
	public void restoreState(Bundle icicle) {
		setMode(PAUSE);

		// mAppleList = coordArrayToArrayList(icicle.getIntArray("mAppleList"));
		// mDirection = icicle.getInt("mDirection");
		// mNextDirection = icicle.getInt("mNextDirection");
		// mMoveDelay = icicle.getLong("mMoveDelay");
		// mScore = icicle.getLong("mScore");
		// mSnakeTrail =
		// coordArrayToArrayList(icicle.getIntArray("mSnakeTrail"));
	}

	private boolean isInPlantbombArea(int x, int y) {
		return  (x>0)&&(x<GameConfg.PLANT_BOMB_SIZE)
		&& (y>mYTileCount*GameConfg.TILE_SIZE-GameConfg.PLANT_BOMB_SIZE)&&(y<mYTileCount*GameConfg.TILE_SIZE);
	}
	
	@Override
	public boolean onTouch(View v, MotionEvent event) {

		logTouchEvent(event);

		if (mMode == GAME_LOST || mMode == GAME_WON) {
			initNewGame();
			setMode(RUNNING);
			update();
			return true;
		} else if (mMode == READY) {
			int y = (int) event.getY(0);

			if (y > 240) {
				control_mode = CONTROL_SENSOR_AND_KEYBORD;
			} else {
				control_mode = CONTROL_TOUCH_AND_KEYBORD;
			}

			initNewGame();
			setMode(RUNNING);
			update();
			return true;
		} else if (mMode == RUNNING && control_mode == CONTROL_TOUCH_AND_KEYBORD) {

			Point h = mHero.getPos();
			int x = (int) event.getX(0);
			int y = (int) event.getY(0);

			switch (event.getAction()) {
			case MotionEvent.ACTION_DOWN:// start moving
				if (isInPlantbombArea(x,y)){
					plantBomb();
					return true;
				}
				isHeroMoving = true;
				mHero.setHeroDirections(resolveDirByTapCoord(h, x, y));
				tapStart = System.currentTimeMillis();
				break;
			case MotionEvent.ACTION_MOVE: // change direction
				mHero.setHeroDirections(resolveDirByTapCoord(h, x, y));
				break;
			case MotionEvent.ACTION_UP: // end moving
				isHeroMoving = false;
				break;
			default:
				break;
			}
	 

			return true;
		} else if (mMode == RUNNING && control_mode == CONTROL_SENSOR_AND_KEYBORD) {

			Point h = mHero.getPos();
			int x = (int) event.getX(0);
			int y = (int) event.getY(0);

			if (event.getAction() == MotionEvent.ACTION_DOWN) { // end moving

				plantBomb();
			}

			return true;
		}
		return false; // indicate event was handled
	}


	/** Show an event in the LogCat view, for debugging */
	private void logTouchEvent(MotionEvent event) {

		String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE", "POINTER_DOWN", "POINTER_UP", "7?",
				"8?", "9?" };
		StringBuilder sb = new StringBuilder();
		int action = event.getAction();
		int actionCode = action & MotionEvent.ACTION_MASK;
		sb.append("TOUCH event ACTION_").append(names[actionCode]);
		if (actionCode == MotionEvent.ACTION_POINTER_DOWN || actionCode == MotionEvent.ACTION_POINTER_UP) {
			sb.append("(pid ").append(action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
			sb.append(")");
		}
		sb.append("[");
		for (int i = 0; i < event.getPointerCount(); i++) {
			sb.append("#").append(i);
			sb.append("(pid ").append(event.getPointerId(i));
			sb.append(")=").append((int) event.getX(i));
			sb.append(",").append((int) event.getY(i));
			if (i + 1 < event.getPointerCount())
				sb.append(";");
		}
		sb.append("]");
		Log.d(LOG_TAG, sb.toString());

	}

	Creature.Direction[] resolveDirByTapCoord(Point pos, int tapX, int tapY) {

		Creature.Direction primaryDir = null;
		Creature.Direction secondaryDir = null;

		int xDiff = tapX - pos.x;
		int yDiff = tapY - pos.y;

		int xMod = Math.abs(xDiff);
		int yMod = Math.abs(yDiff);

		if (xMod <= yMod && yDiff >= 0) {
			primaryDir = Creature.Direction.SOUTH;
			if (xDiff >= 0) {
				secondaryDir = Creature.Direction.EAST;
			} else {
				secondaryDir = Creature.Direction.WEST;
			}
		} else if (xMod <= yMod && yDiff < 0) {
			primaryDir = Creature.Direction.NORTH;
			if (xDiff >= 0) {
				secondaryDir = Creature.Direction.EAST;
			} else {
				secondaryDir = Creature.Direction.WEST;
			}
		} else if (xMod > yMod && xDiff < 0) {
			primaryDir = Creature.Direction.WEST;
			if (yDiff >= 0) {
				secondaryDir = Creature.Direction.SOUTH;
			} else {
				secondaryDir = Creature.Direction.NORTH;
			}
		} else if (xMod > yMod && xDiff >= 0) {
			primaryDir = Creature.Direction.EAST;
			if (yDiff >= 0) {
				secondaryDir = Creature.Direction.SOUTH;
			} else {
				secondaryDir = Creature.Direction.NORTH;
			}
		}

		return new Creature.Direction[] { primaryDir, secondaryDir };
	}

	public ArrayList<Bomb> getBombs() {
		return bombs;
	}

	private SensorManager mSensorManager;
	private Sensor mAccelerometer;
	private Sensor mOrientation;

	public void initSensor() {
		mSensorManager = (SensorManager) this.getContext().getSystemService(Context.SENSOR_SERVICE);
		mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
		mOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
		resumeSensor();
	}

	protected void resumeSensor() {
		mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
		mSensorManager.registerListener(this, mOrientation, SensorManager.SENSOR_DELAY_NORMAL);
	}

	protected void pauseSensor() {
		mSensorManager.unregisterListener(this);
	}

	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		// Log.d(LOG_TAG,"onAccuracyChanged: " + sensor + ", accuracy: " +
		// accuracy);

	}

	@Override
	public void onSensorChanged(SensorEvent event) {

		if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
			float[] val = event.values;
			Log.d(LOG_TAG, "========================================");
			Log.d(LOG_TAG, "SENSOR Orientation X ");
			Log.d(LOG_TAG, "SENSOR Orientation Y ");
			Log.d(LOG_TAG, "SENSOR Orientation Z ");
			Log.d(LOG_TAG, "SENSOR X ");
			Log.d(LOG_TAG, "SENSOR Y ");
			Log.d(LOG_TAG, "SENSOR Z ");
			Log.d(LOG_TAG, "		SENSOR ACC X " + val[0]);
			Log.d(LOG_TAG, "		SENSOR ACC Y " + val[1]);
			Log.d(LOG_TAG, "		SENSOR ACC Z " + val[2]);
			Log.d(LOG_TAG, "========================================");

		} else if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
			float[] val = event.values;
			Log.d(LOG_TAG, "========================================");
			Log.d(LOG_TAG, "SENSOR Orientation X " + (int) val[0]);
			Log.d(LOG_TAG, "SENSOR Orientation Y " + (int) val[1]);
			Log.d(LOG_TAG, "SENSOR Orientation Z " + (int) val[2]);
			Log.d(LOG_TAG, "SENSOR X ");
			Log.d(LOG_TAG, "SENSOR Y ");
			Log.d(LOG_TAG, "SENSOR Z ");
			Log.d(LOG_TAG, "		SENSOR ACC X ");
			Log.d(LOG_TAG, "		SENSOR ACC Y ");
			Log.d(LOG_TAG, "		SENSOR ACC Z ");
			Log.d(LOG_TAG, "========================================");
			mHero.setDir(resolveDirSensorCoord(val[0], val[1], val[2]));
		} else {
			// Log.d(LOG_TAG, "SENSOR other event:"+event.sensor.getType());
			float[] val = event.values;
			Log.d(LOG_TAG, "========================================");
			Log.d(LOG_TAG, "SENSOR Orientation X ");
			Log.d(LOG_TAG, "SENSOR Orientation Y ");
			Log.d(LOG_TAG, "SENSOR Orientation Z ");
			Log.d(LOG_TAG, "SENSOR X " + val[0]);
			Log.d(LOG_TAG, "SENSOR Y " + val[1]);
			Log.d(LOG_TAG, "SENSOR Z " + val[2]);
			Log.d(LOG_TAG, "		SENSOR ACC X ");
			Log.d(LOG_TAG, "		SENSOR ACC Y ");
			Log.d(LOG_TAG, "		SENSOR ACC Z ");
			Log.d(LOG_TAG, "========================================");
		}
	}

	Creature.Direction resolveDirSensorCoord(float sensX, float sensY, float sensZ) {

		Creature.Direction ret = Creature.Direction.SOUTH;

		if (sensY < -GameConfg.MIN_ANGLE_TO_PERFORM_TURN) {
			isHeroMoving = true;
			ret = Creature.Direction.SOUTH;
		} else if (sensY > GameConfg.MIN_ANGLE_TO_PERFORM_TURN) {
			isHeroMoving = true;
			ret = Creature.Direction.NORTH;
		} else if (sensZ > GameConfg.MIN_ANGLE_TO_PERFORM_TURN) {
			isHeroMoving = true;
			ret = Creature.Direction.WEST;
		} else if (sensZ < -GameConfg.MIN_ANGLE_TO_PERFORM_TURN) {
			isHeroMoving = true;
			ret = Creature.Direction.EAST;
		} else {
			isHeroMoving = false;
		}

		return ret;
	}

}
